using System;
using System.Web.Security;
using System.Configuration;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using MvcCms.Web.Code;
using MvcCms.Service.Logging;
using MvcCms.Service.Code.Wiki;
using Microsoft.Practices.ServiceLocation;
using MvcCms.Web.Ioc;
using Castle.Windsor;
using Castle.MicroKernel.Registration;
using System.Reflection;
using System.Diagnostics;
using MvcCms.Service.Filters;
using MvcCms.Service.Models;
using Castle.Windsor.Installer;

namespace MvcCms.Web
{
    public class MvcApplication : HttpApplication, IContainerAccessor
    {
        private static IWindsorContainer _container;
        public IWindsorContainer Container
        {
            get { return _container; }
        }

        private static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("favicon.ico");
            AreaRegistration.RegisterAllAreas();

            #region MvcCms Routes

            routes.MapRoute(
                "SiteMap", // Route name
                "sitemap",
                new { controller = "SiteMap", action = "Index" }
                );
            //Page Not Found Route and Members Only Route and SSL Required Route
            routes.MapRoute(
                "PreviewUnPublished", // Route name
                "previewunpublished", // URL with parameters
                new { controller = "Home", action = "PreviewUnPublished", id = "" } // Parameter defaults
                );
            routes.MapRoute(
                "NotFound", // Route name
                "notfound", // URL with parameters
                new { controller = "Home", action = "NotFound", id = "" } // Parameter defaults
                );
            routes.MapRoute(
                "Error", // Route name
                "error", // URL with parameters
                new { controller = "Home", action = "Error", id = "" } // Parameter defaults
                );
            routes.MapRoute(
                "MembersOnly", // Route name
                "membersonly", // URL with parameters
                new { controller = "Home", action = "MembersOnly", id = "" } // Parameter defaults
                );
            routes.MapRoute(
                "SSLRequired", // Route name
                "sslrequired", // URL with parameters
                new { controller = "Home", action = "sslrequired", id = "" } // Parameter defaults
                );

            //Ajax Route with routeval appended to pass timestamp for caching or other items.
            var routeVals = new RouteValueDictionary { { "controller", "backofficeajax" } };
            RouteTable.Routes.Add(new Route("backofficeAjax/{action}/{Id}/{routeval}", new MvcRouteHandler())
            {
                Defaults = routeVals
            });

            routeVals = new RouteValueDictionary { { "controller", "backoffice" } };
            RouteTable.Routes.Add(new Route("backoffice/{action}/{Id}/{routeval}", new MvcRouteHandler())
            {
                Defaults = routeVals
            });

            routeVals = new RouteValueDictionary { { "controller", "homeajax" } };
            RouteTable.Routes.Add(new Route("mvccmsAjax/{action}/{routeval}", new MvcRouteHandler())
            {
                Defaults = routeVals
            });
            routeVals = new RouteValueDictionary { { "controller", "forumajax" } };
            RouteTable.Routes.Add(new Route("forumAjax/{action}/{routeval}", new MvcRouteHandler())
            {
                Defaults = routeVals
            });

            routeVals = new RouteValueDictionary { { "controller", "home" } };
            RouteTable.Routes.Add(new Route("mvccmsModal/{action}/{Id}/{routeval}", new MvcRouteHandler())
            {
                Defaults = routeVals
            });

            routeVals = new RouteValueDictionary { { "controller", "home" }, { "action", "index" } };
            RouteTable.Routes.Add(new Route("translated/{parentPageId}/{languagePathId}", new MvcRouteHandler())
            {
                Defaults = routeVals
            });
            #endregion

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = "" } // Parameter defaults
                );

        }

        protected void Application_Start()
        {
            InitializeWindsor();
            Routing.SetAppRoutes();
            RegisterRoutes(RouteTable.Routes);
            WikiPlex.Macros.Register<TitleLinkMacro>();
            WikiPlex.Macros.Register<TextColorMacro>();
            WikiPlex.Macros.Register<TextSizeMacro>();
            WikiPlex.Macros.Register<AnyStyleMacro>();
            //MvcCms.Web.Code.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);

            Application.Add("ReservedPathNames", ConfigurationManager.AppSettings["ReservedPathNames"]);

            ViewEngines.Engines.Clear();
            var themeViewEngineRazor = ServiceLocator.Current.GetInstance<ThemeViewEngineRazor>();
            var themeViewEngine = ServiceLocator.Current.GetInstance<ThemeViewEngine>();
            ViewEngines.Engines.Add(themeViewEngineRazor);
            ViewEngines.Engines.Add(themeViewEngine);

            //RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterSchedulerContainer();

            ModelBinders.Binders.Add(typeof(DataTablesRequest), new DataTablesModelBinding());
            ModelBinders.Binders.Add(typeof(MvcCmsMobileGridRequest), new MvcCmsMobileGridModelBinding());

            AppLogging.GetLogger(true).Info("Application starting");
        }

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        private void RegisterControllerFactory()
        {
            _container.Register(
              Component
                .For<IControllerFactory>()
                .ImplementedBy<WindsorControllerFactory>()
                .LifeStyle.Singleton
              );
            var controllerFactory = _container.Resolve<IControllerFactory>();
            ControllerBuilder.Current.SetControllerFactory(controllerFactory);
        }

        private void RegisterAllInstallable()
        {
            _container.Install(FromAssembly.This());
        }

        private void RegisterSchedulerContainer()
        {
            _container.Install(FromAssembly.Named("MvcCms.Scheduler"));
        }

        protected virtual void InitializeWindsor()
        {
            if (_container == null)
            {
                // create a new Windsor Container
                _container = ContainerBuilder.Build("Ioc\\Configuration\\Windsor.config");
                ServiceLocator.SetLocatorProvider(() => _container.Resolve<IServiceLocator>());

                _container.Register(Component.For<IWindsorContainer>().Instance(_container));
                _container.Register(Component.For<IActionInvoker>().ImplementedBy<WindsorActionInvoker>());

                RegisterControllerFactory();
                RegisterAllInstallable();

            }
        }
        protected void Application_End()
        {
            AppLogging.GetLogger(true).Info("Application ending");
        }

    }
}